#include <strsafe.h>
#include "definitions.h"
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"d3d9.lib")


void InitGraphics();
void InitD3D(HWND);
void RenderFrame();
void ClearD3D();

void InitGraphics()
{
	D3DXCreateTeapot(d3ddev, &Teapot, nullptr);
	TeapotMtrl.Ambient = D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
	TeapotMtrl.Diffuse = D3DXCOLOR(1.0f,0.0f,0.0f,0.5f);
	TeapotMtrl.Specular = D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
	TeapotMtrl.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
	TeapotMtrl.Power = 5.0f;
	D3DXCreateSphere(d3ddev, 0.6f, 20, 20, &Sphere, nullptr);
	SphereMtrl.Ambient = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f);
	SphereMtrl.Diffuse = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f);
	SphereMtrl.Specular = D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f);
	SphereMtrl.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
	SphereMtrl.Power = 5.0f;

	ZeroMemory(&light, sizeof(D3DLIGHT9));
	light.Type = D3DLIGHT_DIRECTIONAL;
	light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	light.Ambient = D3DXCOLOR(0.2f,0.2f,0.2f,1.0f);
	light.Specular = D3DXCOLOR(0.6f,0.6f,0.6f,1.0f);
	light.Direction = D3DXVECTOR3(0.707f, 0.0f, 0.707f);

	d3ddev->SetLight(0, &light);
	d3ddev->LightEnable(0, true);

	d3ddev->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	d3ddev->SetRenderState(D3DRS_SPECULARENABLE, true);

	d3ddev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
	d3ddev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
	
	d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	d3ddev->SetRenderState(D3DRS_LIGHTING, true);
}
void RenderFrame()
{
	d3ddev->Clear(0, nullptr, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x000000ff, 0.0f, 0);
	d3ddev->BeginScene();
	D3DXMATRIX matView;
	D3DXMatrixLookAtLH(
		&matView,
		&D3DXVECTOR3(0, 0, 10),
		&D3DXVECTOR3(0, 0, 0),
		&D3DXVECTOR3(0, 1, 10)
	);
	d3ddev->SetTransform(D3DTS_VIEW, &matView);

	D3DXMATRIX matProjection;
	D3DXMatrixPerspectiveFovLH(
		&matProjection,
		D3DXToRadian(45),
		(float)WINDOW_WIDTH / (float)WINDOW_HEIGHT,
		1,
		1000
	);
	d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);
	d3ddev->SetMaterial(&SphereMtrl);
	Sphere->DrawSubset(0);
	
	d3ddev->SetMaterial(&TeapotMtrl);
	d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
	Teapot->DrawSubset(0);
	d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	d3ddev->EndScene();
	d3ddev->Present(nullptr, nullptr, nullptr, nullptr);
}
void InitD3D(HWND hWnd)
{
	d3d = Direct3DCreate9(D3D_SDK_VERSION);
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
	d3dpp.Windowed = TRUE;
	d3dpp.hDeviceWindow = hWnd;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferWidth = WINDOW_WIDTH;
	d3dpp.BackBufferHeight = WINDOW_HEIGHT;
	d3d->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp,
		&d3ddev
	);
	InitGraphics();
}
void ClearD3D()
{
	d3ddev->Release();
	d3d->Release();
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_CHAR:
		switch (wParam)
		{
		case 'q':
			TeapotMtrl.Diffuse.a += 0.02f;
			if (TeapotMtrl.Diffuse.a > 1.0f)TeapotMtrl.Diffuse.a = 1.0f;
			break;
		case 'e':
			TeapotMtrl.Diffuse.a -= 0.02f;
			if (TeapotMtrl.Diffuse.a < 0.0f)TeapotMtrl.Diffuse.a = 0.0f;
			break;
		}
		wParam = 0;
	}
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
BOOL RegClass(HINSTANCE hInstance, LPCTSTR lpszClassName, LPCTSTR lpszMenuName, WNDPROC lpfnWndProc)
{
	WNDCLASS a;
	a.style = CS_HREDRAW | CS_VREDRAW;
	a.hInstance = hInstance;
	a.lpfnWndProc = lpfnWndProc;
	a.lpszClassName = lpszClassName;
	a.lpszMenuName = lpszMenuName;
	a.cbClsExtra = 0;
	a.cbWndExtra = 0;
	a.hIcon = LoadIcon(0, IDI_APPLICATION);
	a.hCursor = LoadCursor(0, IDC_ARROW);
	a.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	return RegisterClass(&a);
}